package com.school.generator.service.impl;

import cn.hutool.core.date.DateUtil;
import com.school.generator.bean.BaseBean;
import com.school.generator.bean.DataSourceConfig;
import com.school.generator.bean.FiledBean;
import com.school.generator.mapper.CodeGeneratorMapper;
import com.school.generator.service.RawDataService;
import com.school.generator.util.DateType;
import com.school.generator.util.MainDataUtil;
import com.school.generator.util.MySqlTypeConvert;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

@Component
public class RawDataServiceImpl implements RawDataService {

    @Autowired
    private FreeMarkerConfigurer configurer;

    @Resource
    private CodeGeneratorMapper codeGeneratorMapper;

    @Override
    public void generateProjectFiles(BaseBean baseBean, ZipOutputStream zip) throws Exception {
        //  TODO 生成类名,首字母小写类名,字段数量
        String tableName = baseBean.getTableName();
        String caseName = MainDataUtil.lineToHump(tableName);
        baseBean
                .setBeanCaseName(caseName).
                setBeanName(MainDataUtil.captureName(caseName));


        List<String> arrField = new ArrayList<>();
        List<FiledBean> collect = baseBean.getQueryConditions().stream().map(res -> {
            arrField.add(res.getFieldName());
            String substring = res.getFieldType();
            if (substring.contains("(")) {
                substring = res.getFieldType().substring(0, res.getFieldType().indexOf("("));
            }
            System.out.println(MySqlTypeConvert.processTypeConvert(substring, DateType.ONLY_DATE).getType());
            res.setBeanField(MainDataUtil.lineToHump(res.getFieldName()))
                    .setBeanCapitalField(MainDataUtil.captureName(MainDataUtil.lineToHump(res.getFieldName())))
                    .setDate(DateUtil.format(new Date(), "yyyy-MM-dd"))
                    //将JDBC类型映射成为java类型
                    .setFieldType(MySqlTypeConvert.processTypeConvert(substring, DateType.ONLY_DATE).getType())
            ;
            return res;
        }).collect(Collectors.toList());

        baseBean.setFields(arrField).setQueryConditions(collect).setFieldSize(arrField.size()-1);


        Map<String, String> fileMapping = DataSourceConfig.getDataSourceConfig().getFileMapping();
        for (String s : fileMapping.keySet()) {
            Map<Object, Object> msg = new HashMap<>();
            msg.put("element" , baseBean);
            freemarker.template.Template template = configurer.getConfiguration().getTemplate("/ftl/" + s);
            String tmp = FreeMarkerTemplateUtils.processTemplateIntoString(template, msg);

            String javaFile = "java/";
            try {
                String packagePath = baseBean.getPackagePath().replace("." , "/");
                String type;
                switch (fileMapping.get(s)) {
                    case "service":
                        type = baseBean.getServicePackageName()+"/"+MainDataUtil.captureName(caseName) + "Service.java";
                        break;
                    case "bean":
                        type = baseBean.getBeanPackageName()+"/"+MainDataUtil.captureName(caseName)  + "Entity.java";
                        break;
                    case "mapper":
                        type = baseBean.getMapperPackageName()+"/"+MainDataUtil.captureName(caseName) + "Mapper.java";
                        break;
                    case "xml":
                        type = baseBean.getMapperPackageName() + "/xml/"+MainDataUtil.captureName(caseName) + "Mapper.xml";
                        break;
                    case "controller":
                        type = baseBean.getControllerPackageName()+"/"+ MainDataUtil.captureName(caseName) + "Controller.java";
                        break;
                    default:
                        type = "service/impl/"+MainDataUtil.captureName(caseName) + "ServiceImpl.java";
                }


                zip.putNextEntry(new ZipEntry(replaceLast(javaFile + "/" + packagePath + "/" + type , ".ftl" , "")));
                IOUtils.write(tmp, zip, "UTF-8");
                zip.flush();
                zip.closeEntry();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    public static String replaceLast(String text, String strToReplace, String replaceWithThis) {
        return text.replaceFirst("(?s)" + strToReplace + "(?!.*?" + strToReplace + ")" , replaceWithThis);
    }

    @Override
    public List<Map<String, String>> tableList(String database) {
        return codeGeneratorMapper.tableList(database);
    }

    @Override
    public BaseBean getBaseBean(String tableName) {
        DataSourceConfig.getDataSourceConfig().setDatabase("backstage_admin");
        String database = DataSourceConfig.getDataSourceConfig().getDatabase();
        if (StringUtils.isEmpty(database)) {
            throw new RuntimeException("database name is null");
        }

        BaseBean baseBean = new BaseBean();
        List<FiledBean> byTableFieldList = codeGeneratorMapper.getByTableFieldList(tableName,database);
        Map<String, String> tInfo= codeGeneratorMapper.tableInfo(database,tableName);

        baseBean.setQueryConditions(byTableFieldList);
        baseBean.setNotesTable(tInfo.get("TABLE_COMMENT"));
        baseBean.setTableName(tableName);
        return baseBean;
    }


}
